#ifndef BZN_H_
#define BZN_H_

#include "types.h"

/*
 * Magic numbers for the bzn header and footer
 */
#define MAGIC_HEADER	0xDEADBEEF
#define MAGIC_FOOTER	0x0E0F0E0F

/*
 * Type of constant in the constant field
 */
#define TYPE_BOOLEAN	0x01
#define TYPE_BYTE		0x02
#define TYPE_UBYTE		0x82
#define TYPE_SHORT		0x03
#define TYPE_USHORT		0x83
#define TYPE_INT		0x04
#define TYPE_UINT		0x84
#define TYPE_FLOAT		0x05
#define TYPE_LONG		0x06
#define TYPE_ULONG		0x86
#define TYPE_DOUBLE		0x07
#define TYPE_STRING		0x0A
#define TYPE_OBJECT		0x0B
#define TYPE_CLASS		0x0C
#define TYPE_METHOD		0x0D
#define TYPE_PROPERTY	0x0E
#define TYPE_FIELD		0x0F
#define TYPE_FUNC_PTR	0x1A

/*
 * Accessers for packages, classes, methods, and fields
 */
#define ACCESS_PUBLIC		0x01
#define ACCESS_PRIVATE		0x02
#define ACCESS_PROTECTED	0x04
#define ACCESS_STATIC		0x08
#define ACCESS_FINAL		0x10
#define ACCESS_SYNC			0x20
#define ACCESS_ABSTRACT		0x40
#define ACCESS_NATIVE		0x80

/*
 * Helper defines to check if an access flag is set
 */
#define IS_ACCESS_PUBLIC(flag) 		( ( flag & ACCESS_PUBLIC ) == ACCESS_PUBLIC )
#define IS_ACCESS_PRIVATE(flag) 	( ( flag & ACCESS_PRIVATE ) == ACCESS_PRIVATE )
#define IS_ACCESS_PROTECTED(flag) 	( ( flag & ACCESS_PROTECTED ) == ACCESS_PROTECTED )
#define IS_ACCESS_STATIC(flag) 		( ( flag & ACCESS_STATIC ) == ACCESS_STATIC )
#define IS_ACCESS_FINAL(flag) 		( ( flag & ACCESS_FINAL ) == ACCESS_FINAL )
#define IS_ACCESS_SYNC(flag) 		( ( flag & ACCESS_SYNC ) == ACCESS_SYNC )
#define IS_ACCESS_ABSTRACT(flag) 	( ( flag & ACCESS_ABSTRACT ) == ACCESS_ABSTRACT )
#define IS_ACCESS_NATIVE(flag) 		( ( flag & ACCESS_NATIVE ) == ACCESS_NATIVE )

/*
 * Definitions of a 'signiture' of a method, field, or object
 */
#define s_sig_boolean 	'Z'
#define s_sig_byte		'B'
#define s_sig_ubyte		'b'
#define s_sig_short		'S'
#define s_sig_ushort	's'
#define s_sig_int		'I'
#define s_sig_uint		'i'
#define s_sig_float		'F'
#define s_sig_double	'D'
#define s_sig_long		'L'
#define s_sig_ulong		'l'
#define s_sig_string	'@'
#define s_sig_array		'['
#define s_sig_void		'V'
#define s_sig_obj_start	'$'
#define s_sig_sep		'.'
#define s_sig_obj_end	';'
#define s_sig_ctor		"<ctor>"
#define s_sig_dtor		"<dtor>"

/*
 * Indexes for the various pools
 */
typedef s_ushort s_class_index;
typedef s_ushort s_const_index;
typedef s_ushort s_field_index;
typedef s_ushort s_method_index;
typedef s_ushort s_string_index;
typedef s_ushort s_attribute_index;
typedef s_ushort s_code_index;

typedef struct _const_pool_info {
	s_ubyte type;
	s_byte *data;
} const_pool_info;

typedef struct _method_pool_info {
	s_ubyte access_flag;
	s_string_index name_index;
	s_string_index signature_index;
	s_code_index code_index;
	s_ushort attribute_count;
	s_attribute_index *attribute_indexes;
} method_pool_info;

typedef struct _field_pool_info {
	s_ubyte access_flag;
	s_string_index name_index;
	s_string_index signature_index;
	s_ushort attribute_count;
	s_attribute_index *attribute_indexes;
} field_pool_info;

typedef struct _attribute_pool_info {
	s_string_index name_index;
	s_uint length;
	s_byte *data;
} attribute_pool_info;

typedef struct _code_pool_info {
	s_ptr return_address;
	s_ushort max_local;
	s_ushort attribute_count;
	s_attribute_index *attribute_indexes;
	s_uint length;
	s_byte *code;
} code_pool_info;

typedef struct _bzn_file {
	s_uint magic_header;
	s_uint hash[4];
	
	s_ushort major_version;
	s_ushort minor_version;
	s_ushort access_flag;
	
	s_ushort const_pool_count;
	s_uint const_pool_size;
	s_class_index this_index;
	
	s_ushort inherit_pool_count;
	
	s_ushort field_pool_count;
	s_ushort attribute_pool_count;
	s_uint field_pool_size;
	s_uint attribute_pool_size;
	
	s_method_index constructor_index;
	s_ushort method_pool_count;
	s_uint method_pool_size;
	
	s_ushort string_pool_encoding;
	s_ushort string_pool_count;
	s_uint string_pool_size;
	
	s_code_index code_constructor_index;
	s_ushort code_pool_count;
	s_uint code_pool_size;
	
	const_pool_info *const_pool;
	
	s_class_index *inherit_pool;
		
	field_pool_info *field_pool;
	
	attribute_pool_info *attribute_pool;
	
	method_pool_info *method_pool;
	
	s_string *string_pool;
	
	code_pool_info *code_pool;
	
	s_uint magic_footer;
} bzn_file;

#endif /*BZN_H_*/
